/* MEM @ 500Mhz */
/* GPU @ 400Mhz */
#define DDR_REFC   4
#define DDR_DIV    1
#if (DDR_CLOCK_RATE == 500000000)
#define DDR_DIV_L2 6
#else
#define DDR_DIV_L2 4
#endif
#define GPU_DIV_L2 0x3f

#define PLL_IN     OSC_CLK
#define DDR_LOOPC  ((DDR_CLOCK_RATE*DDR_DIV_L2*DDR_REFC)/(PLL_IN))
#define HDA_DIV_L2 (((PLL_IN)*DDR_LOOPC)/(DDR_REFC*24000000))

/* CPU @ 1000Mhz */
#define L1_REFC    1
#define L1_DIV     1

#define L2_REFC    L1_REFC
#define L2_DIV     2

#define L1_LOOPC   ((CPU_CLOCK_RATE*L2_DIV*L1_REFC)/(PLL_IN))
#define L2_LOOPC   L1_LOOPC


/* DC @ 250Mhz */
/* GMAC @ 125Mhz */
#define DC_LOOPC   10
#define DC_REFC    1
#define DC_DIV     1
#define DC_DIV_L2  4
#define GMAC_DIV   8

#define PIX0_LOOPC  10
#define PIX0_REFC   1
#define PIX0_DIV    1
#define PIX0_DIV_L2 8

#define PIX1_LOOPC  10
#define PIX1_REFC   1
#define PIX1_DIV    1
#define PIX1_DIV_L2 8

#define PLL_CHANG_COMMIT 0x1

#define PLL_L1_LOCKED  (0x1 << 16)
#define PLL_L1_ENA     (0x1 << 2)
#define PLL_MEM_LOCKED (0x1 << 16)
#define PLL_MEM_ENA    (0x1 << 2)

ls2k_clk_config:

	//NODE
	li.d  t0, PHYS_TO_UNCACHED(0x1fe00480)
	li.d  t1, (0x1 << 19) 	//power down pll L1 first
	st.d  t1, t0, 0x0
	li.d  t1, (L2_LOOPC << 54) | (L2_REFC  << 48) | (L1_DIV << 42) | (L1_LOOPC << 32) | (L1_REFC << 26) | (0x3 << 10) | (0x1 << 7)
	li.d  t2, L2_DIV
	st.d  t1, t0, 0x0
	st.d  t2, t0, 0x8
	ori   t1, t1, PLL_L1_ENA
	st.d  t1, t0, 0x0
	//freqscale
	li.d  t2, PHYS_TO_UNCACHED(0x1fe004d0)
	ld.w  a0, t2, 0x0
	li.w  t1, 0xff8fffff
	and   a0, t1, a0
	li.w  a1, (APB_FREQSCALE << 20) //设置APB分频配置
	or    a0, a0, a1
	st.w  a0, t2, 0x0

11:
	ld.d   a0, t0, 0x0
	li.d   a1, PLL_L1_LOCKED
	and    a0, a1, a0
	beqz   a0, 11b //wait_locked_sys
	nop

	ld.d   a0, t0, 0x0
	ori    a0, a0, PLL_CHANG_COMMIT
	st.d   a0, t0, 0x0
	nop


	//DDR
	li.d   t0, PHYS_TO_UNCACHED(0x1fe00490)
	li.d   t1, (0x1 << 19) 	//power down pll  first
	st.d   t1, t0, 0x0
	li.d   t1, (DDR_DIV << 42) | (DDR_LOOPC << 32) | (DDR_REFC << 26) | (0x3 << 10) | (0x1 << 7)
	li.d   t2, (HDA_DIV_L2 << 44) | (GPU_DIV_L2 << 22) | (DDR_DIV_L2)
	st.d   t1, t0, 0x0
	st.d   t2, t0, 0x8
	ori    t1, t1, PLL_L1_ENA
	st.d   t1, t0, 0x0

21:
	ld.w   a0, t0, 0x0
	li.w   a1, PLL_MEM_LOCKED
	and    a0, a0, a1
	beqz   a0, 21b //wait_locked_ddr
	nop

	ld.w   a0, t0, 0x0
	ori    a0, a0, 0x3
	st.w   a0, t0, 0x0
	nop


	//DC
	li.d   t0, PHYS_TO_UNCACHED(0x1fe004a0)
	li.d   t1, (0x1 << 19) 	//power down pll  first
	st.d   t1, t0, 0x0
	li.d   t1, (DC_DIV << 42) | (DC_LOOPC << 32) | (DC_REFC << 26) | (0x3 << 10) | (0x1 << 7)
	li.d   t2, (GMAC_DIV << 22) | (DC_DIV_L2)
	st.d   t1, t0, 0x0
	st.d   t2, t0, 0x8
	ori    t1, t1, PLL_L1_ENA
	st.d   t1, t0, 0x0

21:
	ld.w   a0, t0, 0x0
	li.w   a1, PLL_MEM_LOCKED
	and    a0, a0, a1
	beqz   a0, 21b
	nop

	//apb频率改变后再次初始化调试串口，apb频率通过gmac频率分频出来，默认125MHz
	li.d  a0, (APB_CLOCK_RATE/16)/CONFIG_BAUDRATE
	bl    ls2k1000_uart_init
	nop

	li.d   t0, PHYS_TO_UNCACHED(0x1fe004a0)
	ld.w   a0, t0, 0x0
	ori    a0, a0, 0x3
	st.w   a0, t0, 0x0
	nop


	//PIX0
	li.d   t0, PHYS_TO_UNCACHED(0x1fe004b0)		//pll_pix0
	li.w   t1, (0x1 << 19) 	//power down pll  first
	st.d   t1, t0, 0x0
	li.d   t1, (PIX0_DIV << 42) | (PIX0_LOOPC << 32) | (PIX0_REFC << 26) | (0x3 << 10) | (0x1 << 7)
	li.d   t2, PIX0_DIV_L2
	st.d   t1, t0, 0x0
	st.d   t2, t0, 0x8
	ori    t1, t1, PLL_L1_ENA
	st.d   t1, t0, 0x0

21:
	ld.w   a0, t0, 0x0
	li.w   a1, PLL_MEM_LOCKED
	and    a0, a0, a1
	beqz   a0, 21b
	nop

	ld.w   a0, t0, 0x0
	ori    a0, a0, 0x1
	st.w   a0, t0, 0x0
	nop


	//PIX1
	li.d   t0, PHYS_TO_UNCACHED(0x1fe004c0)		//pll_pix1
	li.w   t1, (0x1 << 19) 	//power down pll  first
	st.d   t1, t0, 0x0
	li.d   t1, (PIX1_DIV << 42) | (PIX1_LOOPC << 32) | (PIX1_REFC << 26) | (0x3 << 10) | (0x1 << 7)
	li.d   t2, PIX1_DIV_L2
	st.d   t1, t0, 0x0
	st.d   t2, t0, 0x8
	ori    t1, t1, PLL_L1_ENA
	st.d   t1, t0, 0x0

21:
	ld.w   a0, t0, 0x0
	li.w   a1, PLL_MEM_LOCKED
	and    a0, a0, a1
	beqz   a0, 21b
	nop

	li.d   t0, PHYS_TO_UNCACHED(0x1fe004d0)		//freq_scale
	li.d   t1, (1 << 33) | (1 << 32) | (APB_FREQSCALE << 20) | (7 << 16) | (7 << 12) | (7 << 8) | (7 << 0)
	st.d   t1, t0, 0x0

	ld.w   a0, t0, 0x0
	ori    a0, a0, 0x1
	st.w   a0, t0, 0x0
	nop
